<?php
/**
 * Copyright 2009, OpenScriptures.org
 * GPL 3 License: http://www.gnu.org/licenses/gpl.html
 * $Id: reference-parser.lib.php 158 2009-02-25 17:25:04Z WestonRuter@gmail.com $
 */


/**
 * Convert OSIS Ref into a conventional reference
 */
$osisBookNames = array(
	"Gen" => "Genesis",
	"Exod" => "Exodus",
	"Lev" => "Leviticus",
	"Num" => "Numbers",
	"Deut" => "Deuteronomy",
	"Josh" => "Joshua",
	"Judg" => "Judges",
	"Ruth" => "Ruth",
	"1Sam" => "1 Samuel",
	"2Sam" => "2 Samuel",
	"1Kgs" => "1 Kings",
	"2Kgs" => "2 Kings",
	"1Chr" => "1 Chronicles",
	"2Chr" => "2 Chronicles",
	"Ezra" => "Ezra",
	"Neh" => "Nehemiah",
	"Esth" => "Esther",
	"Job" => "Job",
	"Ps" => "Psalms",
	"Prov" => "Proverbs",
	"Eccl" => "Ecclesiastes",
	"Song" => "Song of Solomon",
	"Isa" => "Isaiah",
	"Jer" => "Jeremiah",
	"Lam" => "Lamentations",
	"Ezek" => "Ezekiel",
	"Dan" => "Daniel",
	"Hos" => "Hosea",
	"Joel" => "Joel",
	"Amos" => "Amos",
	"Obad" => "Obadiah",
	"Jonah" => "Jonah",
	"Mic" => "Micah",
	"Nah" => "Nahum",
	"Hab" => "Habakkuk",
	"Zeph" => "Zephaniah",
	"Hag" => "Haggai",
	"Zech" => "Zechariah",
	"Mal" => "Malachi",
	
	"Matt" => "Matthew",
	"Mark" => "Mark",
	"Luke" => "Luke",
	"John" => "John",
	"Acts" => "Acts",
	"Rom" => "Romans",
	"1Cor" => "1 Corinthians",
	"2Cor" => "2 Corinthians",
	"Gal" => "Galatians",
	"Eph" => "Ephesians",
	"Phil" => "Philippians",
	"Col" => "Colossians",
	"1Thess" => "1 Thessalonians",
	"2Thess" => "2 Thessalonians",
	"1Tim" => "1 Timothy",
	"2Tim" => "2 Timothy",
	"Titus" => "Titus",
	"Phlm" => "Philemon",
	"Heb" => "Hebrews",
	"Jas" => "James",
	"1Pet" => "1 Peter",
	"2Pet" => "2 Peter",
	"1John" => "1 John",
	"2John" => "2 John",
	"3John" => "3 John",
	"Jude" => "Jude",
	"Rev" => "Revelation",
	
	"Bar" => "Baruch",
	"AddDan" => "Additions to Daniel",
	"PrAzar" => "Prayer of Azariah",
	"Bel" => "Bel and the Dragon",
	"SgThree" => "Song of the Three Young Men",
	"Sus" => "Susanna",
	"1Esd" => "1 Esdras",
	"2Esd" => "2 Esdras",
	"AddEsth" => "Additions to Esther",
	"EpJer" => "Epistle of Jeremiah",
	"Jdt" => "Judith",
	"1Macc" => "1 Maccabees",
	"2Macc" => "2 Maccabees",
	"3Macc" => "3 Maccabees",
	"4Macc" => "4 Maccabees",
	"PrMan" => "Prayer of Manasseh",
	"Sir" => "Sirach/Ecclesiasticus",
	"Tob" => "Tobit",
	"Sir" => "Sirach/Ecclesiasticus",
	"Wis" => "Wisdom of Solomon"
);
function format_osisref($osisref){
	global $osisBookNames;
	@list($start, $end) = split('-', $osisref);
	$ref = '';
	
	#Parse start osisref
	$regexp = '/^(\w+)(?:\.(\d+)(?:\.(\d+))?)?/';
	if(!preg_match($regexp, $start, $startMatches))
		return $ref;
	
	$startBook = @$startMatches[1];
	$startChapter = @$startMatches[2];
	$startVerse = @$startMatches[3];
	
	#Construct the start osisref
	$ref = $osisBookNames[$startBook];
	if($startChapter){
		$ref .= " $startChapter";
		if($startVerse)
			$ref .= ":$startVerse";
	}
	
	#Parse the end osisref
	if(!preg_match($regexp, $end, $endMatches))
		return $ref;
	$endBook = @$endMatches[1];
	$endChapter = @$endMatches[2];
	$endVerse = @$endMatches[3];
	
	if($endVerse && !$startVerse){
		$ref .= ":1";
		$startVerse = 1;
	}
	
	#Construct the end osisref
	if($startBook != $endBook || !$endVerse){
		if($startBook == $endBook && !$startVerse && !$endVerse){
			$ref .= "-$endChapter";
		}
		else {
			$ref .= " - ";
			$ref .= $osisBookNames[$endBook];
			if($endChapter){
				$ref .= " $endChapter";
				if($endVerse)
					$ref .= ":$endVerse";
			}
		}
	}
	else if($endChapter && $startChapter != $endChapter){
		$ref .= "-$endChapter";
		if($endVerse)
			$ref .= ":$endVerse";
	}
	else if($endVerse && $startVerse != $endVerse){
		$ref .= "-$endVerse";
	}
	
	return $ref;
}

/**
 * Takes a conventional reference and returns an osisRef; does the inverse of format_osisref
 */
$ntBookRegExps = array(
	array('/^1\s*C\D*/i',			"1Cor"),
	array('/^1\s*J\D*/i',			"1John"),
	array('/^1\s*P\D*/i',			"1Pet"),
	array('/^1\s*Th\D*/i',			"1Thess"),
	array('/^1\s*T[im]\D*/i',		"1Tim"),
	array('/^2\s*C\D*/i',			"2Cor"),
	array('/^2\s*J\D*/i',			"2John"),
	array('/^2\s*P\D*/i',			"2Pet"),
	array('/^2\s*Th\D*/i',			"2Thess"),
	array('/^2\s*T[im]\D*/i',		"2Tim"),
	array('/^3\s*J\D*/i',			"3John"),
	array('/^A\D*/i',				"Acts"),
	array('/^C\D*/i',				"Col"),
	array('/^E\D*/i',				"Eph"),
	array('/^G\D*/i',				"Gal"),
	array('/^H\D*/i',				"Heb"),
	array('/^J[mas]\D*/i',			"Jas"),
	array('/^Jo?[hn]\D*/i',			"John"),
	array('/^Ju\D*/i',				"Jude"),
	array('/^L\D*/i',				"Luke"),
	array('/^Ma?[rk]\D*/i',			"Mark"),
	array('/^Ma?t?t\D*/i',			"Matt"),
	array('/^Ph\w*m\D*/i',			"Phlm"),
	array('/^Ph(il|\w*p)\D*/i',		"Phil"),
	array('/^Ph\D*/i',				"Phil"),
	array('/^R[ev]\D*/i',			"Rev"),
	array('/^R[om]\D*/i',			"Rom"),
	array('/^T\D*/i',				"Titus")
);

/**
 * Returns an osisRef
 */
function parse_reference($ref){
	global $ntBookRegExps;
	$parts = preg_split('/\s*-+\s*/', preg_replace('/–|—/', '-', preg_replace('/^\s+|\s+$/', '', $ref)));  #.replace(/\u2013|\u2014/g, '-').split(/\s*-+\s*/);
	
	$osisref = '';
	$startBook = 0;
	$startChapter = 0;
	$startVerse = 0;
	$endBook = 0;
	$endChapter = 0;
	$endVerse = 0;
	
	//Parse the start ref
	foreach($ntBookRegExps as $bookRegExp){
		if(preg_match($bookRegExp[0], $parts[0])){
			//Get book
			$startBook = $bookRegExp[1];
			$parts[0] = preg_replace($bookRegExp[0], '', $parts[0]);
			
			//Chapter
			if(preg_match('/(\d+)(?:\D+(\d+)(?:\s*,\s*(\d+))?)?/', $parts[0], $chapVerseParts)){
				$startChapter = intval($chapVerseParts[1]);
				
				//Verse
				if(@$chapVerseParts[2])
					$startVerse = intval($chapVerseParts[2]);
				
				//If a comma is separating two verses then honor that
				if(@$chapVerseParts[3]){
					$endBook = $startBook;
					$endChapter = $startChapter;
					$endVerse = intval($chapVerseParts[3]);
					if($endVerse != $startVerse+1)
						$endVerse = null;
				}
			}
			break;
		}
	}
	if(!$startBook)
		return '';
	
	$osisref = $startBook;
	if($startChapter)
		$osisref .= '.' . $startChapter;
	if($startVerse)
		$osisref .= '.' . $startVerse;
	
	//If reference is range, parse the ending ref
	if(@$parts[1]){
		foreach($ntBookRegExps as $bookRegExp){
			if(preg_match($bookRegExp[0], $parts[1])){
				$endBook = $bookRegExp[1];
				$parts[1] = preg_replace($bookRegExp[0], '', $parts[1]);
				break;
			}
		}
			
		//Chapter
		if(preg_match('/(\d+)(?:\D+(\d+))?/', $parts[1], $chapVerseParts)){
			
			//If only one number is in ref end, and there is no book specified
			if(!@$chapVerseParts[2] && !$endBook){
				//If verse specified in start ref, then the number is the verse
				if($startVerse){
					$endChapter = $startChapter;
					$endVerse = intval($chapVerseParts[1]);
				}
				//If only chapter specified, then the number is a chapter
				else if($startChapter){
					$endChapter = intval($chapVerseParts[1]);
				}
			}
			//Either the book is supplied or a chapter and verse is supplied; in this case, don't adopt anything from start ref
			else {
				$endChapter = intval($chapVerseParts[1]);
				if(@$chapVerseParts[2])
					$endVerse = intval($chapVerseParts[2]);
			}
		}
		
		if(!$endBook)
			$endBook = $startBook;
	}

	if($endBook){
		$osisref .= '-' . $endBook;
		if($endChapter)
			$osisref .= '.' . $endChapter;
		if($endVerse)
			$osisref .= '.' . $endVerse;
	}
	
	//1 John 3:1,2
	//1 John 3:2-1 John 3:3
	//1 John 3-1 John 4
	//1 John 1:2-1 John 4:2
	
	return $osisref;
}

